package com.api.aiyh_pcn.patentWall.service;

import aiyh.utils.Util;
import aiyh.utils.zwl.common.ToolUtil;
import com.alibaba.fastjson.JSON;
import com.api.aiyh_pcn.patentWall.dao.PatentWallMapping;
import com.api.aiyh_pcn.patentWall.dto.FilterWhere;
import com.api.aiyh_pcn.patentWall.vo.LinkUrlVO;
import com.api.aiyh_pcn.patentWall.vo.PatentVO;
import com.api.aiyh_pcn.patentWall.vo.SearchInputVO;
import com.api.aiyh_pcn.patentWall.vo.SelectOptionsVo;
import weaver.conn.RecordSet;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author EBU7-dev1-ayh
 * @create 2021/11/25 0025 15:23
 */
public class PatentWallService {
  private final PatentWallMapping patentWallMapping = new PatentWallMapping();
  private final ToolUtil toolUtil = new ToolUtil();
  private Map<String, Object> patentWallConf;
  private Map<String, Object> patentWallSearchConf;
  private final RecordSet rs = new RecordSet();

  /**
   * 查询搜索框配置信息
   *
   * @param prefix 前缀
   * @return 配置信息
   */
  public List<SearchInputVO> getSearchList(String prefix, int languageId) {
    Map<String, Object> patentWallSearchConf = getPatentWallSearchConf(prefix + ".search");
    String dataResource = String.valueOf(patentWallSearchConf.get("dataResource"));
    List<Map<String, Object>> inputs =
        (List<Map<String, Object>>) patentWallSearchConf.get("inputs");
    List<SearchInputVO> searchInputList = new ArrayList<>();
    for (Map<String, Object> input : inputs) {
      SearchInputVO searchInputVO = new SearchInputVO();
      int type = Integer.parseInt(Util.null2DefaultStr(input.get("type"), "0"));
      String dbFieldName = Util.null2String(input.get("dbFieldName"));
      String value = Util.null2String(input.get("value"));
      String labelName = Util.null2String(input.get("labelName"));
      Integer labelIndex = Integer.valueOf(Util.null2DefaultStr(input.get("labelIndex"), "0"));
      Integer searchType = Integer.valueOf(Util.null2DefaultStr(input.get("searchType"), "0"));
      Boolean multiple = Boolean.valueOf(Util.null2DefaultStr(input.get("multiple"), "false"));
      searchInputVO.setType(type);
      searchInputVO.setLabelName(labelName);
      searchInputVO.setSearchType(searchType);
      searchInputVO.setDbFieldName(dbFieldName);
      searchInputVO.setLabelIndex(labelIndex);
      searchInputVO.setLabelIndex(labelIndex);
      searchInputVO.setMultiple(multiple);
      searchInputVO.setValue(value);
      searchInputList.add(searchInputVO);
      switch (type) {
        case 1:
          //					下拉框 查询options
          List<SelectOptionsVo> optionsVos =
              getSelectOptions(dataResource, dbFieldName, languageId);
          searchInputVO.setSelectOptions(optionsVos);
        case 2:
          //					单行文本
          break;
        case 3:
          //                  日期
        case 4:
          //                  单人力资源
          break;
        case 5:
          //                  多人力资源
          break;
        case 6:
          //                  流程路径
          break;
        case 7:
          //                  多流程路径
          break;
        default:
          toolUtil.writeDebuggerLog("未匹配输入框类型！请检查配置文件是否正确！");
          break;
      }
    }
    return searchInputList;
  }

  private List<SelectOptionsVo> getSelectOptions(
      String dataResource, String dbFieldName, int languageId) {
    List<Map<String, Object>> selectOptions =
        patentWallMapping.getSelectOptions(dataResource, dbFieldName);
    List<SelectOptionsVo> optionsVos = new ArrayList<>();
    SelectOptionsVo optionsDefault = new SelectOptionsVo();
    optionsDefault.setSelected(true);
    optionsDefault.setKey("");
    optionsDefault.setShowname("");
    optionsVos.add(optionsDefault);
    for (Map<String, Object> selectOption : selectOptions) {
      SelectOptionsVo optionsVo = new SelectOptionsVo();
      optionsVo.setSelected(false);
      optionsVo.setKey(Util.null2DefaultStr(selectOption.get("selectvalue"), ""));
      String selectName = Util.null2DefaultStr(selectOption.get("selectname"), "");
      String showName = selectName;
      if (selectName.startsWith("~`~`") && selectName.endsWith("`~`~")) {
        String pattern = "(`~`" + languageId + " )(?<label>(\\w*|\\W*|[\\u4e00-\\u9fa5]*))(`~`)";
        Pattern compile = Pattern.compile(pattern);
        Matcher matcher = compile.matcher(selectName);
        if (matcher.find()) {
          showName = matcher.group("label");
        }
      }
      optionsVo.setShowname(showName);
      optionsVos.add(optionsVo);
    }
    return optionsVos;
  }

  /**
   * 查询结果信息
   *
   * @param filterWheres 结果过滤条件
   * @param prefix 前缀
   * @return 查询结果
   */
  public List<PatentVO> getList(List<FilterWhere> filterWheres, String prefix) {
    Map<String, Object> patentWallConf = getPatentWallConf(prefix + ".voMapping");
    List<Map<String, Object>> dataList;
    toolUtil.writeDebuggerLog(String.format("查询数据，接收到的过滤信息为： %s", JSON.toJSONString(filterWheres)));
    if (filterWheres == null || filterWheres.isEmpty()) {
      //			查询全部
      dataList = patentWallMapping.getAllList(Util.null2String(patentWallConf.get("dataResource")));
    } else {
      //			筛选查询
      dataList =
          handleFilterWhere(filterWheres, Util.null2String(patentWallConf.get("dataResource")));
    }
    List<PatentVO> list = new ArrayList<>();
    List<String> args = new ArrayList<>();
    RecordSet rs = new RecordSet();
    for (Map<String, Object> data : dataList) {
      Map<String, Object> config = new HashMap<>(patentWallConf);
      for (Map.Entry<String, Object> entry : patentWallConf.entrySet()) {
        String patentVoField = entry.getKey();
        //				linkList
        String parsing = null;
        //				值解析
        if ("linkList".equals(patentVoField)) {
          List<LinkUrlVO> linkUrlVOS = new ArrayList<>();
          List<Map<String, Object>> linkUrlList = (List<Map<String, Object>>) entry.getValue();
          for (Map<String, Object> linkUrlMap : linkUrlList) {
            LinkUrlVO linkUrlVO = new LinkUrlVO();
            BeanInfo beanInfo = null;
            try {
              beanInfo = Introspector.getBeanInfo(LinkUrlVO.class, Object.class);
            } catch (IntrospectionException e) {
              e.printStackTrace();
              toolUtil.writeDebuggerLog("获取beanInfo错误");
              continue;
            }
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
              String keyName = propertyDescriptor.getName();
              String parsingValue = String.valueOf(linkUrlMap.get(keyName));
              parsingValue = handleParsingConf(parsingValue, data, args);
              //				清除参数信息
              args.clear();
              if (propertyDescriptor.getPropertyType().equals(Integer.class)) {
                try {
                  propertyDescriptor
                      .getWriteMethod()
                      .invoke(linkUrlVO, Integer.valueOf(parsingValue));
                } catch (IllegalAccessException | InvocationTargetException e) {
                  toolUtil.writeErrorLog("设置值失败，调用beanInfo的set方法错误");
                  e.printStackTrace();
                }
              } else {
                try {
                  propertyDescriptor.getWriteMethod().invoke(linkUrlVO, parsingValue);
                } catch (IllegalAccessException | InvocationTargetException e) {
                  e.printStackTrace();
                  toolUtil.writeErrorLog("设置值失败，调用beanInfo的set方法错误");
                }
              }
            }
            linkUrlVOS.add(linkUrlVO);
          }
          config.replace(patentVoField, linkUrlVOS);
        } else {
          parsing = String.valueOf(entry.getValue());
          parsing = handleParsingConf(parsing, data, args);
          //				修改数据
          config.replace(patentVoField, parsing);
          //				清除参数信息
          args.clear();
        }
      }
      PatentVO patentVO = null;
      try {
        patentVO = Util.mapToObject(config, PatentVO.class);
      } catch (Exception e) {
        e.printStackTrace();
        toolUtil.writeErrorLog("map转为PatentVO失败！");
      }
      list.add(patentVO);
    }
    return list;
  }

  public String handleParsingConf(String parsing, Map<String, Object> data, List<String> args) {
    //				 值解析
    //				解析 ${}类型的参数，直接替换
    String pattern = "\\$\\{(?<field>(\\s|\\S)+?)}";
    Pattern compile = Pattern.compile(pattern);
    Matcher matcher = compile.matcher(parsing);
    while (matcher.find()) {
      parsing = parsing.replaceFirst(pattern, Util.null2String(data.get(matcher.group("field"))));
    }
    //				解析#{}类型的参数，替换为?并按照顺序收集args
    pattern = "#\\{(?<field>(\\s|\\S)+?)}";
    compile = Pattern.compile(pattern);
    matcher = compile.matcher(parsing);
    while (matcher.find()) {
      parsing = parsing.replaceFirst(pattern, "?");
      args.add(Util.null2String(data.get(matcher.group("field"))));
    }
    //				解析#sql{}类型的参数，并执行SQL，获取到SQL的值
    pattern = "#sql\\{(?<sqlStr>([\\s\\S])+?)}";
    compile = Pattern.compile(pattern);
    matcher = compile.matcher(parsing);
    while (matcher.find()) {
      String sqlStr = matcher.group("sqlStr");
      toolUtil.writeDebuggerLog(String.format("执行SQL： {%s} ---> 参数： {%s}", sqlStr, args));
      rs.executeQuery(sqlStr, args);
      rs.next();
      parsing = parsing.replaceFirst(pattern, Util.null2String(rs.getString(1)));
      ;
    }
    return parsing;
  }

  public List<Map<String, Object>> handleFilterWhere(
      List<FilterWhere> filterWheres, String tableName) {
    StringBuilder whereBuilder = new StringBuilder(" where ");
    List<String> args = new ArrayList<>();
    for (FilterWhere filterWhere : filterWheres) {
      whereBuilder.append(" add ");
      if (filterWhere.getSearchType() == 1) {
        //				等于
        whereBuilder.append(filterWhere.getDbField()).append(" = ? ");
        args.add(filterWhere.getValue());
        continue;
      }
      if (filterWhere.getSearchType() == 2) {
        //				大于
        whereBuilder.append(filterWhere.getDbField()).append(" > ?");
        args.add(filterWhere.getValue());
        continue;
      }
      if (filterWhere.getSearchType() == 3) {
        //              小于
        whereBuilder.append(filterWhere.getDbField()).append(" < ?");
        args.add(filterWhere.getValue());
        continue;
      }
      if (filterWhere.getSearchType() == 4) {
        //				in
        whereBuilder
            .append(filterWhere.getDbField())
            .append(" in ( ")
            .append(filterWhere.getValue())
            .append(") ");
        continue;
      }
      if (filterWhere.getSearchType() == 5) {
        //				日期大于
        whereBuilder
            .append(" DATE_FORMAT(")
            .append(filterWhere.getDbField())
            .append(",'%y-%m-%d') > ")
            .append("DATE_FORMAT(?,'%y-%m-%d')");
        args.add(filterWhere.getValue());
        continue;
      }
      if (filterWhere.getSearchType() == 6) {
        //				日期小于
        whereBuilder
            .append(" DATE_FORMAT(")
            .append(filterWhere.getDbField())
            .append(",'%y-%m-%d') < ")
            .append("DATE_FORMAT(?,'%y-%m-%d')");
        args.add(filterWhere.getValue());
        continue;
      }
      if (filterWhere.getSearchType() == 7) {
        //				日期等于
        whereBuilder
            .append(" DATE_FORMAT(")
            .append(filterWhere.getDbField())
            .append(",'%y-%m-%d') = ")
            .append("DATE_FORMAT(?,'%y-%m-%d')");
        args.add(filterWhere.getValue());
        continue;
      }
      if (filterWhere.getSearchType() == 8) {
        //				日期范围
        whereBuilder
            .append(" DATE_FORMAT(")
            .append(filterWhere.getDbField())
            .append(",'%y-%m-%d')  between ")
            .append("DATE_FORMAT(?,'%y-%m-%d')")
            .append(" and DATE_FORMAT(?,'%y-%m-%d')");
        args.add(filterWhere.getValue().split("&")[0]);
        args.add(filterWhere.getValue().split("&")[1]);
        continue;
      }
    }
    return patentWallMapping.getListByFilterWhere(whereBuilder, args, tableName);
  }

  /**
   * 获取单例的配置文件信息
   *
   * @return
   */
  private Map<String, Object> getPatentWallConf(String prefix) {
    synchronized (this) {
      if (this.patentWallConf == null) {
        this.patentWallConf = Util.readProperties2Map("PatentWall", "aiyh." + prefix);
      }
      if (this.patentWallConf == null) {
        return new HashMap<>(0);
      }
      return new HashMap<>(this.patentWallConf);
    }
  }

  public void clearPatentWallConf() {
    this.patentWallConf = null;
  }

  /**
   * 获取单例的配置文件信息
   *
   * @return
   */
  private Map<String, Object> getPatentWallSearchConf(String prefix) {
    synchronized (this) {
      if (this.patentWallSearchConf == null) {
        this.patentWallSearchConf = Util.readProperties2Map("PatentWall", "aiyh." + prefix);
      }
      if (this.patentWallSearchConf == null) {
        return new HashMap<>(0);
      }
      return new HashMap<>(this.patentWallSearchConf);
    }
  }

  public void clearPatentWallSerachConf() {
    this.patentWallSearchConf = null;
  }
}
